using System.Collections;
using UnityEngine;
using System.Collections.Generic;
using Framework.Utils;

namespace Framework.Manager
{
    public class AudioManager : MonoBehaviour
    {
        class SoundInfo
        {
            public float vol;
            public AudioSource audioSource;

            public SoundInfo(float volume, AudioSource audioSource)
            {
                vol = volume;
                this.audioSource = audioSource;
            }
        }

        private bool musicOn = true;
        private bool effectOn = true;
        private float _musicVolume = 1f;
        private float _effectVolume = 1f;
        private List<SoundInfo> effectsList; //正在播放的音效列表
        private AudioSource mainMusic; //背景音乐，同一时间只能由一首BGM在播放

        private void Awake()
        {
            effectsList = new List<SoundInfo>();

            //读取本地数据
            musicOn = PlayerPrefsEx.GetBool("musicOn", true);
            effectOn = PlayerPrefsEx.GetBool("soundOn", true);
            _musicVolume = PlayerPrefs.GetFloat("musicVolume", 1);
            _effectVolume = PlayerPrefs.GetFloat("soundVolume", 1);

            mainMusic = gameObject.AddComponent<AudioSource>();
            _instance = this;
        }

        private static AudioManager _instance = null;

        /// <summary>
        /// 音效管理器单例
        /// </summary>
        public static AudioManager Instance => _instance;

        //音乐开关
        public bool MusicOn
        {
            get { return musicOn; }
        }

        public void SetMusicOn(bool value)
        {
            if (value == musicOn)
            {
                return;
            }

            musicOn = value;
            if (musicOn)
            {
                if (mainMusic != null)
                {
                    mainMusic.volume = MusicVolume;
                }
            }
            else
            {
                if (mainMusic != null)
                {
                    mainMusic.volume = 0;
                }
            }
        }

        //音效开关
        public bool EffectOn
        {
            get { return effectOn; }
        }

        public void SetEffectOn(bool value)
        {
            if (value == EffectOn)
                return;
            effectOn = value;
            if (effectOn == false)
            {
                for (int i = effectsList.Count - 1; i >= 0; i--)
                {
                    effectsList[i].audioSource.volume = 0;
                }
            }
            else
            {
                for (int i = effectsList.Count - 1; i >= 0; i--)
                {
                    effectsList[i].audioSource.volume = effectsList[i].vol * EffectVolume;
                }
            }
        }

        //音乐音量
        public float MusicVolume
        {
            get { return _musicVolume; }
        }

        public void SetMusicVolume(float value)
        {
            value = value < 0 ? 0 : value;
            value = value > 1 ? 1 : value;
            _musicVolume = value;
            mainMusic.volume = value;
        }

        //音效音量
        public float EffectVolume
        {
            get { return _effectVolume; }
        }

        public void SetEffectsVolume(float value)
        {
            value = value < 0 ? 0 : value;
            value = value > 1 ? 1 : value;
            float oldValue = _effectVolume;
            _effectVolume = value;
            for (int i = effectsList.Count - 1; i >= 0; i--)
            {
                effectsList[i].audioSource.volume *= effectsList[i].vol * value;
            }
        }

        //保存数据到本地
        public void SaveData()
        {
            PlayerPrefs.SetFloat("soundVolume", EffectVolume);
            PlayerPrefs.SetFloat("musicVolume", MusicVolume);
            PlayerPrefsEx.SetBool("soundOn", EffectOn);
            PlayerPrefsEx.SetBool("musicOn", MusicOn);
        }

        #region 音乐

        //播放音乐
        public void PlayMusic(AudioClip bgmClip, float volume = 1f, bool loop = true)
        {
            mainMusic.Stop();
            mainMusic.clip = bgmClip;
            mainMusic.loop = loop;
            mainMusic.Play();
            if (musicOn)
            {
                mainMusic.volume = volume * MusicVolume;
            }
            else
            {
                mainMusic.volume = 0;
            }
        }

        public void StopMusic()
        {
            mainMusic.Stop();
        }

        public void PauseMusic()
        {
            mainMusic.Pause();
        }

        public void ResumeMusic()
        {
            if (musicOn && Time.timeScale != 0)
            {
                mainMusic.Play();
            }
        }

        #endregion

        #region 音效

        //播放音效
        public void PlaySound(AudioClip soundClip, float volume = 0.5f, bool isRealTime = false)
        {
            AudioClip sound = soundClip;
            AudioSource source = gameObject.AddComponent<AudioSource>();
            source.clip = sound;
            source.volume = EffectVolume;
            source.loop = false;
            SoundInfo info = new SoundInfo(volume, source);
            effectsList.Add(info);
            source.Play();

            if (EffectOn)
            {
                source.volume = volume * EffectVolume;
            }
            else
            {
                source.volume = 0;
            }

            if (isRealTime)
            {
                StartCoroutine(DoDestroyByRealTime(info, sound.length));
            }
            else
            {
                StartCoroutine(DoDestroy(info, sound.length));
            }
        }

        IEnumerator DoDestroyByRealTime(SoundInfo info, float delay)
        {
            yield return new WaitForSecondsRealtime(delay);
            DestroySound(info);
        }
    
        IEnumerator DoDestroy(SoundInfo info, float delay)
        {
            yield return new WaitForSeconds(delay);
            DestroySound(info);
        }
        
        void DestroySound(SoundInfo info)
        {
            effectsList.Remove(info);
            Destroy(info.audioSource);
        }
        
        public void PauseAllSounds()
        {
            foreach (SoundInfo info in effectsList)
            {
                info.audioSource.Pause();
            }
        }

        public void ResumeAllSounds()
        {
            if (EffectOn && Time.timeScale != 0)
            {
                foreach (SoundInfo src in effectsList)
                {
                    src.audioSource.Play();
                }
            }
        }

        public void ClearEffects()
        {
            foreach (SoundInfo src in effectsList)
            {
                Destroy(src.audioSource);
            }

            effectsList.Clear();
        }

        #endregion
    }
}